package cn.xiuxius.embedded.runtime.rtx51;

import com.intellij.codeInsight.hints.*;
import com.intellij.codeInsight.hints.presentation.InlayPresentation;
import com.intellij.codeInsight.hints.presentation.MouseButton;
import com.intellij.codeInsight.hints.presentation.PresentationFactory;
import com.intellij.lang.Language;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.ui.components.JBPanel;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TaskInlayHintsProvider implements InlayHintsProvider<NoSettings> {
    private static final Pattern TASK_PATTERN = Pattern.compile("/\\*\\*\\s*_task_\\s*([a-zA-Z0-9_]+)\\s*\\*\\*/");

    @NotNull
    @Override
    public String getName() {
        return "Task syntax inlay hints";
    }


    @Nullable
    @Override
    public InlayHintsCollector getCollectorFor(@NotNull PsiFile file,
                                               @NotNull Editor editor,
                                               @NotNull NoSettings settings,
                                               @NotNull InlayHintsSink sink) {
        VirtualFile vfile = file.getVirtualFile();
        if (true) {
            return new FactoryInlayHintsCollector(editor) {
                final Set<Integer> addedOffsets = new HashSet<>();
                final PresentationFactory factory = new PresentationFactory(editor);

                @Override
                public boolean collect(@NotNull PsiElement element, @NotNull Editor editor, @NotNull InlayHintsSink sink) {
                    String text = element.getText();
                    Matcher matcher = TASK_PATTERN.matcher(text);

                    while (matcher.find()) {
                        int start = element.getTextRange().getStartOffset() + matcher.start();
                        int end = element.getTextRange().getStartOffset() + matcher.end();
                        String uniqueKey = start + "-" + end;

                        if (!addedOffsets.add(uniqueKey.hashCode())) continue; // 精准去重

                        String taskNumber = matcher.group(1);

                        InlayPresentation textPresentation = factory.roundWithBackground(
                                factory.text("\uD83C\uDFAF Task")
                        );
                        InlayPresentation withTooltip = factory.withTooltip("修改", textPresentation);




                        TaskClickListener listener = new TaskClickListener(editor, element, taskNumber);
                        InlayPresentation clickable = factory.onClick(
                                withTooltip,
                                MouseButton.Left,
                                (MouseEvent e, Point point) -> {
                                    listener.accept(e, point);
                                    return Unit.INSTANCE;
                                }
                        );

                        sink.addInlineElement(start, true, clickable, false);
                    }

                    return true;
                }

            };
        }

        return null;

    }

    @NotNull
    @Override
    public SettingsKey<NoSettings> getKey() {
        return new SettingsKey<>("task.inlay.hints");
    }

    @NotNull
    @Override
    public NoSettings createSettings() {
        return new NoSettings();
    }

    @Override
    public boolean isLanguageSupported(@NotNull Language language) {
        return language.is(Language.findLanguageByID("ObjectiveC")) || language.is(Language.ANY);
    }

    @Nullable
    @Override
    public String getPreviewText() {
        return "void UART_Config() @Task(1) {\n}";
    }

    @NotNull
    @Override
    public ImmediateConfigurable createConfigurable(@NotNull NoSettings settings) {
        return changeListener -> new JBPanel<>();
    }
}
